# -*- coding: utf-8 -*-
# Author   : ZhangQing
# Time     : 2025-08-12 11:00
# File     : audit_logger.py
# Project  : codebuddy_craft
# Desc     : 审计日志系统

"""
审计日志系统 📝

记录系统关键操作的审计日志，支持安全审计和合规要求
"""

import json
import logging
import time
from typing import Dict, Any, Optional, List, Union
from datetime import datetime

from backend.utils.logger import get_logger, get_security_logger
from backend.core.settings import get_settings

settings = get_settings()
logger = get_logger("audit")
security_logger = get_security_logger()


class AuditEvent:
    """审计事件 📝"""
    
    def __init__(
        self,
        event_type: str,
        user_id: Optional[str],
        resource_type: str,
        resource_id: Optional[str],
        action: str,
        status: str,
        details: Optional[Dict[str, Any]] = None,
        ip_address: Optional[str] = None,
        request_id: Optional[str] = None
    ):
        self.event_type = event_type
        self.user_id = user_id
        self.resource_type = resource_type
        self.resource_id = resource_id
        self.action = action
        self.status = status
        self.details = details or {}
        self.ip_address = ip_address
        self.request_id = request_id
        self.timestamp = datetime.utcnow().isoformat()
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "event_type": self.event_type,
            "user_id": self.user_id,
            "resource_type": self.resource_type,
            "resource_id": self.resource_id,
            "action": self.action,
            "status": self.status,
            "details": self.details,
            "ip_address": self.ip_address,
            "request_id": self.request_id,
            "timestamp": self.timestamp
        }
    
    def __str__(self) -> str:
        """字符串表示"""
        return (
            f"AuditEvent[{self.event_type}]: "
            f"用户={self.user_id or 'anonymous'} "
            f"操作={self.action} "
            f"资源={self.resource_type}/{self.resource_id or 'none'} "
            f"状态={self.status}"
        )


class AuditLogger:
    """审计日志记录器 📝"""
    
    def __init__(self):
        self.logger = logger
        self.security_logger = security_logger
        self.event_buffer: List[AuditEvent] = []
        self.buffer_size = settings.AUDIT_BUFFER_SIZE if hasattr(settings, "AUDIT_BUFFER_SIZE") else 100
    
    def log_event(
        self,
        event_type: str,
        user_id: Optional[str],
        resource_type: str,
        resource_id: Optional[str],
        action: str,
        status: str = "success",
        details: Optional[Dict[str, Any]] = None,
        ip_address: Optional[str] = None,
        request_id: Optional[str] = None,
        severity: str = "info"
    ) -> None:
        """记录审计事件

        Args:
            event_type: 事件类型
            user_id: 用户ID
            resource_type: 资源类型
            resource_id: 资源ID
            action: 操作
            status: 状态
            details: 详情
            ip_address: IP地址
            request_id: 请求ID
            severity: 严重程度
        """
        # 创建审计事件
        event = AuditEvent(
            event_type=event_type,
            user_id=user_id,
            resource_type=resource_type,
            resource_id=resource_id,
            action=action,
            status=status,
            details=details,
            ip_address=ip_address,
            request_id=request_id
        )
        
        # 记录日志
        log_level = {
            "debug": logging.DEBUG,
            "info": logging.INFO,
            "warning": logging.WARNING,
            "error": logging.ERROR,
            "critical": logging.CRITICAL
        }.get(severity.lower(), logging.INFO)
        
        self.logger.log(
            log_level,
            str(event),
            extra=event.to_dict()
        )
        
        # 对于安全相关事件，同时记录安全日志
        if event_type.startswith("security."):
            self.security_logger.log_security_alert(
                alert_type=event_type,
                severity=severity,
                description=f"{action} on {resource_type}/{resource_id or 'none'} by {user_id or 'anonymous'} - {status}",
                user_id=user_id,
                resource_type=resource_type,
                resource_id=resource_id,
                action=action,
                status=status,
                ip_address=ip_address,
                request_id=request_id
            )
        
        # 添加到缓冲区
        self.event_buffer.append(event)
        
        # 如果缓冲区已满，则刷新
        if len(self.event_buffer) >= self.buffer_size:
            self.flush_buffer()
    
    def flush_buffer(self) -> None:
        """刷新缓冲区"""
        if not self.event_buffer:
            return
        
        try:
            # 这里可以实现将审计日志批量写入数据库或其他存储
            # 例如：await self._write_to_database(self.event_buffer)
            
            # 清空缓冲区
            self.event_buffer.clear()
            
        except Exception as e:
            self.logger.error(f"刷新审计日志缓冲区失败: {e}")
    
    def log_auth_event(
        self,
        user_id: Optional[str],
        action: str,
        status: str = "success",
        details: Optional[Dict[str, Any]] = None,
        ip_address: Optional[str] = None,
        request_id: Optional[str] = None
    ) -> None:
        """记录认证事件

        Args:
            user_id: 用户ID
            action: 操作
            status: 状态
            details: 详情
            ip_address: IP地址
            request_id: 请求ID
        """
        self.log_event(
            event_type="security.auth",
            user_id=user_id,
            resource_type="auth",
            resource_id=None,
            action=action,
            status=status,
            details=details,
            ip_address=ip_address,
            request_id=request_id,
            severity="warning" if status != "success" else "info"
        )
    
    def log_access_event(
        self,
        user_id: Optional[str],
        resource_type: str,
        resource_id: Optional[str],
        action: str,
        status: str = "success",
        details: Optional[Dict[str, Any]] = None,
        ip_address: Optional[str] = None,
        request_id: Optional[str] = None
    ) -> None:
        """记录访问事件

        Args:
            user_id: 用户ID
            resource_type: 资源类型
            resource_id: 资源ID
            action: 操作
            status: 状态
            details: 详情
            ip_address: IP地址
            request_id: 请求ID
        """
        self.log_event(
            event_type="security.access",
            user_id=user_id,
            resource_type=resource_type,
            resource_id=resource_id,
            action=action,
            status=status,
            details=details,
            ip_address=ip_address,
            request_id=request_id,
            severity="warning" if status != "success" else "info"
        )
    
    def log_data_event(
        self,
        user_id: Optional[str],
        resource_type: str,
        resource_id: Optional[str],
        action: str,
        status: str = "success",
        details: Optional[Dict[str, Any]] = None,
        ip_address: Optional[str] = None,
        request_id: Optional[str] = None
    ) -> None:
        """记录数据事件

        Args:
            user_id: 用户ID
            resource_type: 资源类型
            resource_id: 资源ID
            action: 操作
            status: 状态
            details: 详情
            ip_address: IP地址
            request_id: 请求ID
        """
        self.log_event(
            event_type="data",
            user_id=user_id,
            resource_type=resource_type,
            resource_id=resource_id,
            action=action,
            status=status,
            details=details,
            ip_address=ip_address,
            request_id=request_id
        )
    
    def log_admin_event(
        self,
        user_id: Optional[str],
        resource_type: str,
        resource_id: Optional[str],
        action: str,
        status: str = "success",
        details: Optional[Dict[str, Any]] = None,
        ip_address: Optional[str] = None,
        request_id: Optional[str] = None
    ) -> None:
        """记录管理事件

        Args:
            user_id: 用户ID
            resource_type: 资源类型
            resource_id: 资源ID
            action: 操作
            status: 状态
            details: 详情
            ip_address: IP地址
            request_id: 请求ID
        """
        self.log_event(
            event_type="admin",
            user_id=user_id,
            resource_type=resource_type,
            resource_id=resource_id,
            action=action,
            status=status,
            details=details,
            ip_address=ip_address,
            request_id=request_id,
            severity="warning"  # 管理操作默认为警告级别
        )
    
    def log_system_event(
        self,
        action: str,
        status: str = "success",
        details: Optional[Dict[str, Any]] = None,
        request_id: Optional[str] = None
    ) -> None:
        """记录系统事件

        Args:
            action: 操作
            status: 状态
            details: 详情
            request_id: 请求ID
        """
        self.log_event(
            event_type="system",
            user_id=None,
            resource_type="system",
            resource_id=None,
            action=action,
            status=status,
            details=details,
            request_id=request_id
        )


# 单例实例
_audit_logger: Optional[AuditLogger] = None


def get_audit_logger() -> AuditLogger:
    """获取审计日志记录器 📝

    Returns:
        审计日志记录器
    """
    global _audit_logger
    
    if _audit_logger is None:
        _audit_logger = AuditLogger()
    
    return _audit_logger


# 导出所有公共类和函数
__all__ = [
    'AuditEvent',
    'AuditLogger',
    'get_audit_logger',
]